package com.h2cloud.JUCTest.patten;


import com.sun.org.apache.bcel.internal.generic.NEW;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    public static void main(String[] args) {
//        SyncPrintV2 s = new SyncPrintV2(1, 5);
//        new Thread(() -> {
//            s.print(1, 2, "1");
//        }, "t1").start();
//        new Thread(() -> {
//            s.print(2, 3, "2");
//        }, "t2").start();
//        new Thread(() -> {
//            s.print(3, 1, "3\n");
//        }, "t3").start();

        SyncPrintCount c = new SyncPrintCount();
        new Thread(() -> {
            c.print(1);
        }, "t1").start();
        new Thread(() -> {
            c.print(2);
        }, "t2").start();
        new Thread(() -> {
            c.print(0);
        }, "t3").start();
    }
}

class SyncPrintV2 {
    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    int flag;
    int loopNumber;

    public SyncPrintV2(int flag, int loopNumber) {
        this.flag = flag;
        this.loopNumber = loopNumber;
    }

    public void print(int curFlag, int nextFlag, String str) {
        for (int i = 0; i < loopNumber; i++) {
            lock.lock();
            try {
                while (this.flag != curFlag) {
                    condition.await();
                }
                System.out.print(str);
                this.flag = nextFlag;
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}

class SyncPrint {

    int flag;
    int loopNumber;

    public SyncPrint(int flag, int loopNumber) {
        this.flag = flag;
        this.loopNumber = loopNumber;
    }

    public void print(int curFlag, String str, int nextFlag) {
        for (int i = 0; i < loopNumber; i++) {
            synchronized (this) {
                while (this.flag != curFlag) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.print(str);
                flag = nextFlag;
                this.notifyAll();
            }
        }
    }
}


class SyncPrintCount {
    int count = 1;

    public void print(int flag) {
        while (count <= 100) {
            synchronized (this) {
                while (count % 3 != flag) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                System.out.println(Thread.currentThread().getName() + " = " + count);
                count++;
                if (count > 100) return;
                this.notifyAll();
            }
        }
    }
}